package com.ruyuan.rapid.core.context;

import com.ruyuan.rapid.common.config.Rule;
import io.netty.channel.ChannelHandlerContext;

import java.util.function.Consumer;

/**
 * 全局网关上下文接口
 * @author mac
 */
public interface Context {

    /**
     * 一个请求正在执行过程中
     */
    int RUNNING = -1;
    /**
     * 写回响应标记, 标记当前context/请求需要写回
     */
    int WRITTEN = 0;
    /**
     * 当写回成功后, 设置该标记 ctx.writeAndFlush(response)
     */
    int COMPLETED = 1;
    /**
     * 整个网关请求完毕
     */
    int TERMINATED = 2;

    /**
     * 设置上下文状态为正常运行状态
     */
    void runned();

    /**
     * 设置上下文状态为标记写回状态
     */
    void writtened();

    /**
     * 设置上下文状态为写回结束
     */
    void completed();

    /**
     * 设置上下文状态为最终结束状态
     */
    void terminated();

    /**
     * 判断上下文状态是否正在运行
     * @return
     */
    boolean isRunning();

    /**
     * 判断是否标记写回响应状态
     * @return
     */
    boolean isWritten();

    /**
     * 判断是否写回结束
     * @return
     */
    boolean isCompleted();

    /**
     * 判断请求是否完全结束
     * @return
     */
    boolean isTerminated();

    /**
     * 获取请求转换协议
     * @return
     */
    String getProtocol();

    /**
     * 获取规则
     */
    Rule getRule();

    /**
     * 获取请求对象
     * @return
     */
    Object getRequest();

    /**
     * 获取响应对象
     * @return
     */
    Object getResponse();

    /**
     * 设置响应对象
     */
    void setResponse(Object response);

    /**
     * 设置异常信息
     * @param throwable
     */
    void setThrowable(Throwable throwable);

    /**
     * 返回异常信息
     */
    Throwable getThrowable();

    // TODO: 定义attributeKey对象

    /**
     * 获取上下文参数
     * @param key 对应的key
     * @param <T>
     * @return
     */
    <T> T getAttribute(AttributeKey<T> key);

    /**
     * 设置上下文属性信息
     * @param key
     * @param value 上下文参数值
     * @param <T>
     * @return
     */
    <T> T putAttribute(AttributeKey<T> key, T value);

    /**
     * 获取netty上下文对象
     * @return
     */
    ChannelHandlerContext getNettyCtx();

    /**
     * 是否保持连接
     * @return
     */
    boolean isKeepAlive();

    /**
     * 释放请求资源
     */
    void releaseRequest();

    /**
     * 写回结束回调函数设置
     */
    void completedCallback(Consumer<Context> consumer);

    /**
     * 回调函数执行
     */
    void invokeCompletedCallback();

    /**
     * SS 服务端发送请求时间
     * SR 服务端收到请求实现
     * RS 客户端发送请求时间
     * RR 客户单收到请求时间
     */
    long getSRTime();

    void setSRTime(long srTime);

    long getSSTime();

    void setSSTime(long ssTime);

    long getRSTime();

    void setRSTime(long rsTime);

    long getRRTime();

    void setRRTime(long rrTime);
}
